package com.wideplay.warp.security;

import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.matcher.Matcher;
import com.google.inject.util.Objects;
import com.wideplay.warp.util.Strings;
import net.jcip.annotations.NotThreadSafe;
import org.acegisecurity.userdetails.UserDetailsService;

import java.lang.reflect.Method;

/**
 * Created with IntelliJ IDEA.
 * On: 25/09/2007
 *
 * Instances are expected to be thread confined.
 *
 * @author Dhanji R. Prasanna
 * @since 1.0
 */
@NotThreadSafe
class FluentSecurityModuleBuilderImpl implements MethodSecurityBuilder, SecurityModuleBuilder, AuthenticatorBuilder, AuthRedirectBuilder {
    private final SimpleConfig config = new SimpleConfig();

    public SecurityModuleBuilder secureMethods(Matcher<? super Class<?>> classMatcher, Matcher<? super Method> methodMatcher) {
        this.config.setClassMatcher(classMatcher);
        this.config.setMethodMatcher(methodMatcher);
        
        return this;
    }

    public Module buildModule() {
        //fail the construction process if there are any errors, reporting them via Guice

        return new SecurityModule(config);    //build & return
    }


    public AuthenticatorBuilder authenticate() {
        return this;
    }

    public AuthRedirectBuilder against(Class<? extends UserDetailsService> clazz) {
        Objects.nonNull(clazz, "Must specify an implementation of UserDetailsService to auth against");
        this.config.setUserDetailsService(Key.get(clazz));

        return this;
    }


    public SecurityModuleBuilder orFail(String url) {
        Strings.nonEmpty(url, "Fail url cannot be null or empty");

        config.setFailUrl(url);

        return this;
    }

    public AuthRedirectBuilder welcome(String url) {
        Strings.nonEmpty(url, "Welcome url cannot be null or empty");
        config.setSuccessUrl(url);

        return this;
    }


    public AuthRedirectBuilder exit(String url) {
        Strings.nonEmpty(url, "Exit url cannot be null or empty");
        config.setLogoutUrl(url);

        return this;
    }

    public AuthorizeBuilder at(final String antUrlPattern) {
        Strings.nonEmpty(antUrlPattern, "at(url-pattern) cannot be null or empty");
        
        return new AuthorizeBuilder() {
            public SecurityModuleBuilder authorize(String... roles) {
                config.addAuthorization(antUrlPattern, roles);
                
                return FluentSecurityModuleBuilderImpl.this;
            }
        };
    }
}
